package com.ldgk.pim.client.view.components;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.maps.client.InfoWindow;
import com.google.gwt.maps.client.InfoWindowContent;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.event.MarkerClickHandler;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.overlay.Icon;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.MarkerOptions;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.ldgk.pim.client.event.PlaceEvent;
import com.ldgk.pim.client.util.Util;
import com.ldgk.pim.data.Place;

/**
 * Power Marker - customized map overlay
 * @version 1.0
 *
 */
public class PowerMarker extends Marker{
	/** Map view that is presenting this marker */
	private MapWidget mapWidget;
	/** Point where the marker is being shown */
	private LatLng point;
	/** Distribution Place whose data should be displayed in in the marker */
	private Place distributionPlace;
	/** is local result */
	private boolean isLocalResult=false;
	/** balloon action button */
	private Button balloonButton = new Button();
	
	/** Prevents the info window from being closed in the first 3 seconds (go figure the map events)*/
	private static boolean preventWindowClosing=false;
	/** Last opened info window ever */
	private static InfoWindow lastOpenWindow;
	
	private static final String ADD_TO_DATABASE = "Adicionar ao Banco de Dados";
	private static final String UPDATE_DATA = "Alterar Dados";
	
	
	
	/**
	 * Constructs a PowerMarker from a distribution place
	 * @param distributionPlace
	 * @param point - 
	 * @param mapView - MapView where the marker is being displayed
	 * @param icon
	 */
	public static PowerMarker newInstance(Place p, LatLng point, MapWidget mapWidget, Icon icon, boolean isLocalResult) {
		MarkerOptions options = MarkerOptions.newInstance(icon);
		options.setTitle(p.getName());
		return new PowerMarker(p,point,mapWidget,options,isLocalResult);
	}
	
	
	private PowerMarker(Place distributionPlace, LatLng point, MapWidget mapWidget, MarkerOptions options, boolean isLocalResult) {
		super(point,options);
		this.mapWidget = mapWidget;
		this.distributionPlace = distributionPlace;
		this.isLocalResult = isLocalResult;
		this.point = point;
		
		//Marker click handler, shows the balloon
		this.addMarkerClickHandler(new MarkerClickHandler() {
			public void onClick(MarkerClickEvent event) {
				showBalloon();
			}
	    });
		//Create balloon button
		if( isLocalResult ){
			balloonButton.setText(ADD_TO_DATABASE);
		}else{
			balloonButton.setText(UPDATE_DATA);
		}
	}

	/**
	 * Builds the info window (balloon) over a specific result
	 * TODO handle this control to the presenter
	 * @param result
	 */
	private void showBalloon(){
		PowerMarker.closeAllWindows();
		
		//Create the info window
		final InfoWindow info = this.mapWidget.getInfoWindow();
		lastOpenWindow = info;
		
		InfoWindowContent content;
		
		balloonButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				info.close();
				//Fire appropriate event (ADD / EDIT)
				if( isLocalResult ){
					Util.eventbus.fireEvent(new PlaceEvent(distributionPlace, PlaceEvent.Type.ADD));
				}else{
					Util.eventbus.fireEvent(new PlaceEvent(distributionPlace, PlaceEvent.Type.EDIT));
				}
			}
		});
		
		VerticalPanel pnl = new VerticalPanel();
		pnl.add(new HTML(distributionPlaceToHtml(this.distributionPlace)));
		pnl.add(balloonButton);
		
		content = new InfoWindowContent(pnl);
		
	    preventWindowClosing=true;
	    Timer t = new Timer() {  
            public void run() {
            	preventWindowClosing=false;
            }  
          };  
          t.schedule(5000);  		  		
	    
          info.open(point, content);
	}

	/**
	 * Tells if the marker representes a google search
	 * local result or a distribution place
	 * @return <code>true</code> if the marker represents
	 * a google local result, <code>false</code> if it represents
	 * a distribution place (database entity)
	 */
	public boolean isLocalResult(){
		return this.isLocalResult;
	}

	/**
	 * Enables/disables any info windows from being closed
	 * @param prevent - enable/disable info windows closing
	 */
	public static void preventWindowClosing(boolean prevent){
		preventWindowClosing = prevent;
	}

	/**
	 * Closes all opened info windows
	 */
	public static void closeAllWindows(){
		if( lastOpenWindow != null && !preventWindowClosing){
			lastOpenWindow.close();
		}
	}

	/**
	 * Generates a friendly html string with a Distribution Place's data
	 * @param dp - DistributionPlace
	 * @return html string
	 */
	private String distributionPlaceToHtml(Place dp){
		StringBuilder tmp = new StringBuilder(200);
		//Tittle
		tmp.append("<p><b><h3>").append(dp.getName()).append("</h3></b>");
		//Address
		tmp.append(dp.getAddress() != null? dp.getAddress(): "");
		//Phones
		String[] phones = dp.getPhones() != null? dp.getPhones().split("[|]") : new String[]{};
		if( phones.length > 0){
			tmp.append("<ul>");
			for(int i=0; i<phones.length; i++){
				tmp.append("<li>").append(phones[i]);
			}
			tmp.append("</ul>");
		}
		//Contact Person
		if( dp.getContactPerson() != null )
			tmp.append("<p>Pessoa de contato: ").append(dp.getContactPerson());
		
		return tmp.toString();
	}
}
